a6c2d4
@@ -1040,6 +1040,11 @@
public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
 			}
 			catch (Throwable ex) {
 				clearResources();
+				if (!this.lastMessageSucceeded) {
+					// We failed more than once in a row or on startup - sleep before
+					// first recovery attempt.
+					sleepBeforeRecoveryAttempt();
+				}
 				this.lastMessageSucceeded = false;
 				boolean alreadyRecovered = false;
 				synchronized (recoveryMonitor) {
@@ -1191,6 +1196,17 @@
public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
 			this.session = null;
 		}
 
+		/**
+		 * Apply the back off time once. In a regular scenario, the back off is only applied if we
+		 * failed to recover with the broker. This additional sleep period avoids a burst retry
+		 * scenario when the broker is actually up but something else if failing (i.e. listener
+		 * specific).
+		 */
+		private void sleepBeforeRecoveryAttempt() {
+			BackOffExecution execution = DefaultMessageListenerContainer.this.backOff.start();
+			applyBackOffTime(execution);
+		}
+
 		@Override
 		public boolean isLongLived() {
 			return (maxMessagesPerTask < 0);
